package com.hnit.config;


import com.clickhouse.data.ClickHouseDataType;
import com.hnit.service.ToolServices;
import dev.langchain4j.community.model.dashscope.QwenEmbeddingModel;
import dev.langchain4j.community.store.embedding.clickhouse.ClickHouseEmbeddingStore;
import dev.langchain4j.community.store.embedding.clickhouse.ClickHouseSettings;
import dev.langchain4j.memory.chat.ChatMemoryProvider;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.chat.StreamingChatModel;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
import dev.langchain4j.service.*;
import dev.langchain4j.store.memory.chat.ChatMemoryStore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

@Configuration
public class AiConfig {

    //////////高级API:  带记忆，区分用户,支持流式会话
    public interface Assistant{
        @SystemMessage("你是一位电商网站的客服")
        String chat(@MemoryId String memoryId, @UserMessage String question );  // 需要有一个ChatModel
        @SystemMessage("你是一位电商网站的客服")
        TokenStream chatStream( @MemoryId String memoryId, @UserMessage String question );  //需要有一个StreamingChatModel

    }

    //内存级向量数据库
//    @Bean
//    public InMemoryEmbeddingStore<TextSegment> embeddingStore() {
//        return new InMemoryEmbeddingStore<>();
//    }

    Map<String, ClickHouseDataType> metadataTypeMap = new HashMap<>();


    EmbeddingModel embeddingModel = QwenEmbeddingModel.builder()
            .apiKey(System.getenv("ALI_API_KEY"))
            .build();

    @Bean
    public ClickHouseSettings clickHouseSettings() {
        return ClickHouseSettings.builder()
                .url("http://localhost:8123")
                .table("embeddings_table")
                .username("dy")
                .password("dy666666")
                .dimension(embeddingModel.dimension())
                .metadataTypeMap(metadataTypeMap) // 直接调用方法
                .build();
    }

    @Bean
    public ClickHouseEmbeddingStore embeddingStore(ClickHouseSettings settings) {
        return ClickHouseEmbeddingStore.builder()
                .settings(settings)
                .build();
    }

    //生成代理对象，这个代理 对象要被spring托管, ->才能注入到Controller
    //                     IOC
    @Bean
    public Assistant assistant(ChatModel chatModel,   //需要有一个ChatModel  聊天模型
                               StreamingChatModel streamingChatModel,   //需要有一个StreamingChatModel  流式聊天模型
                               ChatMemoryStore chatMemoryStore,     //需要有一个ChatMemoryStore    记忆
                               ToolServices tools,
                               ClickHouseEmbeddingStore embeddingStore,  //存储 clickhouse
                               QwenEmbeddingModel qwenEmbeddingModel){  //千问模型
        // PersistentChatMemoryStore memoryStore=new PersistentChatMemoryStore();  利用spring 的Di注入 chatMemoryStore对象
        ChatMemoryProvider chatMemoryProvider= memoryId-> MessageWindowChatMemory.builder()
                .id(   memoryId )
                .maxMessages(1000)   //最多1000条
                .chatMemoryStore(   chatMemoryStore )  //记忆
                .build();

        EmbeddingStoreContentRetriever retriever = EmbeddingStoreContentRetriever.builder()
                .embeddingModel(qwenEmbeddingModel)   //千问模型
                .embeddingStore(embeddingStore)  //向量存储 clickhouse
                .build();

        Assistant assistant= AiServices.builder(Assistant.class)
                .chatModel(  chatModel )
                .streamingChatModel( streamingChatModel  )   //流式会话
                .chatMemoryProvider(  chatMemoryProvider )   //记忆
                .tools(  tools )    //工具
                .contentRetriever(retriever)
                .build();
        return assistant;

    }

//    @Bean
//    public InMemoryEmbeddingStore embeddingStore() {
//        List<Document> documents = FileSystemDocumentLoader.loadDocuments("E:\\testdocuments");
//        InMemoryEmbeddingStore<TextSegment> embeddingStore = new InMemoryEmbeddingStore<>();
//        EmbeddingStoreIngestor.ingest(documents, embeddingStore);
//
//       return embeddingStore;
//    }





}